package com.xdcplus.web.service.bd.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.util.StringUtil;
import com.xdcplus.core.utils.BeanUtils;
import com.xdcplus.exceptions.XdcWebException;
import com.xdcplus.mom.constants.NumberConstant;
import com.xdcplus.mom.enums.OpeSaveModeEnum;
import com.xdcplus.mom.enums.ResponseEnum;
import com.xdcplus.mp.service.impl.BaseServiceImpl;
import com.xdcplus.mp.utils.PageableUtils;
import com.xdcplus.mp.utils.PropertyUtils;
import com.xdcplus.pager.vo.PageVO;
import com.xdcplus.web.common.pojo.dto.bd.BdPathDTO;
import com.xdcplus.web.common.pojo.dto.bd.BdPathFilterDTO;
import com.xdcplus.web.common.pojo.entity.bd.BdOpe;
import com.xdcplus.web.common.pojo.entity.bd.BdPath;
import com.xdcplus.web.common.pojo.entity.bd.BdPathi;
import com.xdcplus.web.common.pojo.entity.tool.ToolInfo;
import com.xdcplus.web.common.pojo.query.bd.BdPathQuery;
import com.xdcplus.web.common.pojo.vo.bd.BdOpeVO;
import com.xdcplus.web.common.pojo.vo.bd.BdPathDetailVO;
import com.xdcplus.web.common.pojo.vo.bd.BdPathVO;
import com.xdcplus.web.common.pojo.vo.tool.ToolInfoVO;
import com.xdcplus.web.mapper.bd.BdOpeMapper;
import com.xdcplus.web.mapper.bd.BdPathMapper;
import com.xdcplus.web.mapper.bd.BdPathiMapper;
import com.xdcplus.web.mapper.tool.ToolInfoMapper;
import com.xdcplus.web.service.bd.BdOpeService;
import com.xdcplus.web.service.bd.BdPathService;
import com.xdcplus.web.service.bd.BdPathiService;
import com.xdcplus.web.service.tool.ToolInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * 工艺路线详细表(BdPath)表服务实现类
 *
 * @author Bullion.Yan
 * @since 2023-02-02 17:25:41
 */
@Slf4j
@Service("bdPathService")
public class BdPathServiceImpl extends BaseServiceImpl<BdPathMapper, BdPath, BdPath, BdPathVO> implements BdPathService {

    @Autowired
    protected BdPathMapper bdPathMapper;

    @Autowired
    protected BdPathiService bdPathiService;


    @Autowired
    protected BdPathiMapper bdPathiMapper;

    @Autowired
    protected BdOpeService bdOpeService;

    @Autowired
    protected BdOpeMapper bdOpeMapper;

    @Autowired
    protected ToolInfoMapper toolInfoMapper;

    @Autowired
    protected ToolInfoService toolInfoService;

    @Resource
    protected TransactionTemplate transactionTemplate;

    /**
     * 该方法仅用于默认新增，插入序列尾部;前置插入、后置插入
     * @param bdPathDTO 工艺路线详细表(BdPathDTO)
     * @return
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean saveBdPath(BdPathDTO bdPathDTO) {

        /// 工艺是否存在
        BdOpe bdOpe = bdOpeMapper.queryByOpeCode(bdPathDTO.getCrOpeCode());
        Assert.isTrue(ObjectUtil.isNotNull(bdOpe),ResponseEnum.OPE_NOTFOUND.getMessage());

        // 工艺判重
        LambdaQueryWrapper<BdPath> bdPathLambdaQueryWrapper = new LambdaQueryWrapper<>();
        bdPathLambdaQueryWrapper.eq(BdPath::getPathIdFk,bdPathDTO.getPathIdFk());
        bdPathLambdaQueryWrapper.eq(BdPath::getCrOpeCode,bdPathDTO.getCrOpeCode());
        if (this.baseMapper.selectCount(bdPathLambdaQueryWrapper)>0) {
            throw new XdcWebException(ResponseEnum.OPE_EXIST_IN_PATH);
        }

        BdPath bdPathNew = new BdPath();
        BeanUtil.copyProperties(bdPathDTO, bdPathNew);

        /// 获取路线code写入
        BdPathi bdPathi = bdPathiMapper.selectById(bdPathDTO.getPathIdFk());
        Assert.isTrue(ObjectUtil.isNotNull(bdPathi),ResponseEnum.OPE_PATH_NOTFOUND.getMessage());
        bdPathNew.setPathCode(bdPathi.getPathCode());

        // 默认新增
        boolean isFirstOpe = false;
        BdPath crBdPathDB = null;
        if(ObjectUtil.isNull(bdPathDTO.getBdPathId()) || bdPathDTO.getBdPathId()<=0) {
            // 查找路线队尾元素
            LambdaQueryWrapper<BdPath> bdPathQueryOneWrapper = new LambdaQueryWrapper<>();
            bdPathQueryOneWrapper.eq(BdPath::getPathIdFk,bdPathDTO.getPathIdFk());
            bdPathQueryOneWrapper.orderByDesc(BdPath::getCrPathSeqNo);
            Optional<BdPath> bdPathDBOptional = this.baseMapper.selectList(bdPathQueryOneWrapper).stream().findFirst();
            BdPath bdPathDB = null;

            if (bdPathDBOptional.isPresent()) {
                bdPathDB = bdPathDBOptional.get();

                // 前置站点
                bdPathNew.setPvOpeCode(bdPathDB.getCrOpeCode());
                // 调整序列
                bdPathNew.setCrPathSeqNo( bdPathDB.getCrPathSeqNo() + 1 );
                bdPathNew.setCrOpeSeqNo( Integer.parseInt(bdPathNew.getCrPathSeqNo().toString()) );

            }else {
                isFirstOpe = true;
                bdPathNew.setCrPathSeqNo(1L);
                bdPathNew.setCrOpeSeqNo(1);
            }
        }else{
            //目标工艺
            crBdPathDB = this.baseMapper.selectById(bdPathDTO.getBdPathId());
            //目标工艺判空
            Assert.notNull(crBdPathDB,ResponseEnum.ERROR.getMessage());

            //前置
            if (ObjectUtil.isNotNull(bdPathDTO.getSaveMode())
                    && bdPathDTO.getSaveMode().equals(OpeSaveModeEnum.BEFORE.getCode())) {
                bdPathNew.setPvOpeCode(crBdPathDB.getPvOpeCode());
                bdPathNew.setNxOpeCode(crBdPathDB.getCrOpeCode());
                crBdPathDB.setPvOpeCode(bdPathNew.getCrOpeCode());

                bdPathNew.setCrPathSeqNo(crBdPathDB.getCrPathSeqNo());
                bdPathNew.setCrOpeSeqNo(Integer.parseInt(crBdPathDB.getCrPathSeqNo().toString()));

                crBdPathDB.setCrPathSeqNo(crBdPathDB.getCrPathSeqNo()+1);
                crBdPathDB.setCrOpeSeqNo(Integer.parseInt(crBdPathDB.getCrPathSeqNo().toString()));

            }else {
                bdPathNew.setPvOpeCode(crBdPathDB.getCrOpeCode());
                bdPathNew.setNxOpeCode(crBdPathDB.getNxOpeCode());
                crBdPathDB.setNxOpeCode(bdPathNew.getCrOpeCode());
                // 在后续重新排序中调整
                bdPathNew.setCrPathSeqNo(crBdPathDB.getCrPathSeqNo());
                bdPathNew.setCrOpeSeqNo(Integer.parseInt(crBdPathDB.getCrPathSeqNo().toString()));
            }

            if (StringUtil.isEmpty(crBdPathDB.getPvOpeCode()) &&
                bdPathDTO.getSaveMode().equals(OpeSaveModeEnum.BEFORE.getCode())){
                isFirstOpe = true;
            }

        }

        bdPathNew.setCreatedTime(new Timestamp(DateUtil.current()));

        // 事务管理多表数据操作
        final boolean isFirstOpeFinal = isFirstOpe;
        final BdPath crBdPathDBFinal = crBdPathDB;
        transactionTemplate.executeWithoutResult(transactionStatus -> {
            // 新增新的工艺
            this.save(bdPathNew);


            // 更新前后置工艺关系
            if (ObjectUtil.isNotEmpty(bdPathNew.getPvOpeCode())) {
                LambdaUpdateWrapper<BdPath> updatePvOpeNxWrapper = new LambdaUpdateWrapper<>();
                updatePvOpeNxWrapper.eq(BdPath::getPathIdFk,bdPathDTO.getPathIdFk());
                updatePvOpeNxWrapper.eq(BdPath::getCrOpeCode,bdPathNew.getPvOpeCode());
                updatePvOpeNxWrapper.set(BdPath::getNxOpeCode,bdPathNew.getCrOpeCode());
                this.update(updatePvOpeNxWrapper);
            }

            if (ObjectUtil.isNotEmpty(bdPathNew.getNxOpeCode())) {
                LambdaUpdateWrapper<BdPath> updateNxOpeNxWrapper = new LambdaUpdateWrapper<>();
                updateNxOpeNxWrapper.eq(BdPath::getPathIdFk,bdPathDTO.getPathIdFk());
                updateNxOpeNxWrapper.eq(BdPath::getCrOpeCode,bdPathNew.getNxOpeCode());
                updateNxOpeNxWrapper.set(BdPath::getPvOpeCode,bdPathNew.getCrOpeCode());
                this.update(updateNxOpeNxWrapper);
            }


//            if(isFirstOpeFinal){
//                // 当前站点为起始站点,配置工艺路线起始工序，写入工序ID
//                BdPathi bdPathiDB = bdPathiMapper.selectById(bdPathDTO.getPathIdFk());
//                Assert.notNull(bdPathiDB,ResponseEnum.OPE_PATH_NOTFOUND.getMessage());
//                bdPathiDB.setFirstOpeNo(bdPathNew.getId());
//                bdPathiMapper.updateById(bdPathiDB);
//            }

            // 如果基于目标工艺插入，需要更新目标工艺的位置关系属性
            if (ObjectUtil.isNotNull(crBdPathDBFinal)) {
                this.updateBdPathById(crBdPathDBFinal);
                this.baseMapper.updateBdPathIncreSeqNo(crBdPathDBFinal);
            }

        });

        return true;

    }

    /**
    * @Description 更新工艺实体包含空值字段处理
    * @Author Devin.sang
    * @Date  2023/4/26 19:02
    */

    private boolean updateBdPathById(BdPath bdPath) {
        if (ObjectUtil.isNull(bdPath.getPvOpeCode())) {
            bdPath.setPvOpeCode("");
        }
        if (ObjectUtil.isNull(bdPath.getNxOpeCode())) {
            bdPath.setNxOpeCode("");
        }
        this.updateById(bdPath);
        return true;
    }

    /**
     * 废弃
     * @param bdPathDTO 工艺路线详细表(BdPathDTO)
     * @return
     */
    @Deprecated
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean updateBdPath(BdPathDTO bdPathDTO) {

        BdPath bdPath = this.getById(bdPathDTO.getId());
        if (ObjectUtil.isNull(bdPath)) {
            log.error("updateBdPath() The BdPath does not exist or has been deleted");
            throw new XdcWebException(ResponseEnum.ERROR);
        }

        BeanUtil.copyProperties(bdPathDTO, bdPath);
        bdPath.setUpdatedUser(bdPathDTO.getUpdatedUser());
        bdPath.setUpdatedTime(new Timestamp(DateUtil.current()));

        return this.updateBdPathById(bdPath);
    }

    @Override
    public Boolean saveOrUpdateBatch(List<BdPath> bdPathList) {

        bdPathList.forEach(bdPath -> {
            BdPath bdPathParam = new BdPath();
            bdPathParam.setId(bdPath.getId());
            if (ObjectUtil.isNotNull(bdPath.getId())) {
                bdPath.setId(bdPath.getId());
                bdPath.setUpdatedTime(new Timestamp(DateUtil.current()));
                LambdaUpdateWrapper<BdPath> lambdaUpdate = Wrappers.lambdaUpdate();
                lambdaUpdate.eq(BdPath::getId, bdPath.getId());
                update(bdPath, lambdaUpdate);
            } else {
                bdPath.setCreatedTime(new Timestamp(DateUtil.current()));
                save(bdPath);
            }
        });
        return true;
    }

    @Override
    public Boolean saveOrUpdateBatchByDTOList(List<BdPathDTO> bdPathDTOList) {

        List<BdPath> bdPathList = BeanUtils.copyProperties(bdPathDTOList, BdPath.class);
        return saveOrUpdateBatch(bdPathList);
    }


    /**
     * 调整前后工艺关联
     * 重新排列工艺序列
     * @param id 工艺路线详细表(BdPath)主键
     * @return
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean deleteBdPathLogical(Long id) {

        Assert.notNull(id, ResponseEnum.THE_ID_CANNOT_BE_EMPTY.getMessage());

        BdPath bdPath = this.getById(id);

        if (ObjectUtil.isNull(bdPath)) {
            log.error("deleteBdPath() The BdPath does not exist or has been deleted");
            throw new XdcWebException(ResponseEnum.ERROR);
        }

        /// 判断工序是否被关联为路线的初始工艺
        LambdaQueryWrapper<BdPathi> bdPathLambdaQueryWrapper = new LambdaQueryWrapper<>();
        bdPathLambdaQueryWrapper.eq(BdPathi::getFirstOpeNo,id);
        if (bdPathiMapper.selectCount(bdPathLambdaQueryWrapper)>0) {
            throw new XdcWebException(ResponseEnum.OPE_DELETE_FAILD_PATHI);
        }

        return transactionTemplate.execute(transactionStatus->{

            // 更新前后置工艺关系
            if (ObjectUtil.isNotEmpty(bdPath.getPvOpeCode()) && ObjectUtil.isNotEmpty(bdPath.getNxOpeCode())) {
                LambdaUpdateWrapper<BdPath> updatePvOpeWrapper = new LambdaUpdateWrapper<>();
                updatePvOpeWrapper.eq(BdPath::getPathIdFk,bdPath.getPathIdFk())
                        .eq(BdPath::getCrOpeCode,bdPath.getPvOpeCode());
                updatePvOpeWrapper.set(BdPath::getNxOpeCode,bdPath.getNxOpeCode());
                this.update(updatePvOpeWrapper);

                LambdaUpdateWrapper<BdPath> updateNxOpeWrapper = new LambdaUpdateWrapper<>();
                updateNxOpeWrapper.eq(BdPath::getPathIdFk,bdPath.getPathIdFk())
                        .eq(BdPath::getCrOpeCode,bdPath.getNxOpeCode());
                updateNxOpeWrapper.set(BdPath::getPvOpeCode,bdPath.getPvOpeCode());
                this.update(updateNxOpeWrapper);
            }

            // 改变后序工艺序列号
            this.baseMapper.updateBdPathReduceSeqNo(bdPath);
            return this.removeById(id);

        });

    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean deleteBdPathByIds(String ids) {
        Assert.notNull(ids, ResponseEnum.THE_ID_CANNOT_BE_EMPTY.getMessage());
        List<String> idList = Arrays.asList(ids.split(","));
        if (CollectionUtil.isEmpty(idList)) {
            throw new XdcWebException(ResponseEnum.ERROR);
        }
        idList.forEach(id -> {
            BdPath bdPath = this.getById(id);
            if (ObjectUtil.isNull(bdPath)) {
                log.error("deleteBdPath() The BdPath does not exist or has been deleted");
                throw new XdcWebException(ResponseEnum.ERROR);
            }
        });

        return this.removeByIds(idList);
    }

    private List<BdPath> queryBdPathList(BdPathFilterDTO bdPathFilterDTO) {
        BdPathQuery bdPathQuery = BeanUtil.copyProperties(bdPathFilterDTO, BdPathQuery.class);

        return bdPathMapper.queryBdPath(bdPathQuery);
    }

    @Override
    public List<BdPathVO> queryBdPathVOList(BdPathFilterDTO bdPathFilterDTO) {
        return this.objectConversion(queryBdPathList(bdPathFilterDTO));
    }

    @Override
    public PageVO<BdPathVO> queryBdPath(BdPathFilterDTO bdPathFilterDTO) {
        PageVO<BdPathVO> pageVO = new PageVO<>();

        if (bdPathFilterDTO.getCurrentPage() > NumberConstant.ZERO) {
            PageableUtils.basicPage(bdPathFilterDTO.getCurrentPage(), bdPathFilterDTO.getPageSize(),
                    "asc", "CR_PATH_SEQ_NO");
        }

        List<BdPath> bdPathList = queryBdPathList(bdPathFilterDTO);

        PageInfo<BdPath> pageInfo = new PageInfo<>(bdPathList);
        PropertyUtils.copyProperties(pageInfo, pageVO, this.objectConversion(bdPathList));

        return pageVO;
    }

    @Override
    public BdPathVO queryBdPathById(Long id) {

        Assert.notNull(id, ResponseEnum.THE_ID_CANNOT_BE_EMPTY.getMessage());

        return this.objectConversion(this.getById(id));
    }

    @Override
    public List<BdPathVO> findBdPathByIdPathIdFk(Long pathIdFk) {
        return this.objectConversion(bdPathMapper.findBdPathByIdPathIdFk(pathIdFk));
    }

    @Override
    public List<BdPathDetailVO> getPathDetailInfoByBdPathiId(Long pathIdFk) {
        List<BdPathDetailVO> bdPathDetailVOList = new ArrayList<>();
        Assert.notNull(pathIdFk, ResponseEnum.THE_ID_CANNOT_BE_EMPTY.getMessage());
        //通过pathIdFk获取Path
        List<BdPath> bdPathList = bdPathMapper.findBdPathByIdPathIdFk(pathIdFk);
        Assert.notEmpty(bdPathList, ResponseEnum.THE_BD_PATH_ERROR.getMessage());
        for (BdPath bdPath : bdPathList) {
            BdPathVO bdPathVO = new BdPathVO();
            BeanUtil.copyProperties(bdPath, bdPathVO);
            BdPathDetailVO bdPathDetailVO = new BdPathDetailVO();
            bdPathDetailVO.setBdPathVO(bdPathVO);
            bdPathDetailVOList.add(bdPathDetailVO);
        }
        //通过crOpeCode获取设备组
        List<String> crOpeCodeList = bdPathList.stream().map(BdPath::getCrOpeCode).collect(Collectors.toList());
        List<BdOpe> bdOpeList = bdOpeMapper.queryByOpeCodes(crOpeCodeList);
        Assert.notEmpty(bdOpeList, "没有找到path对应工序管理信息");
        Map<String,String> crOpeCodeMap=bdOpeList.stream().collect(Collectors.toMap(BdOpe::getOpeCode, BdOpe::getOpeName));
        List<String> opeCodes = bdOpeList.stream().map(BdOpe::getOpeCode).distinct().collect(Collectors.toList());
        //根据主信息获取设备信息
        List<ToolInfo> toolInfoList = toolInfoMapper.getToolByOpeCodes(opeCodes);
        Assert.notEmpty(toolInfoList, "没有找到path对应的设备信息");
        //把toolInfo按照groupId进行分组
        List<ToolInfoVO> toolInfoVOList = new ArrayList<>();
        toolInfoList.forEach(toolInfo -> {
            ToolInfoVO toolInfoVO=new ToolInfoVO();
            BeanUtil.copyProperties(toolInfo, toolInfoVO);
            toolInfoVOList.add(toolInfoVO);

        });

        //把设备信息赋值给对应的BdPath
        bdPathDetailVOList.forEach(bdPathDetailVO -> {
            bdPathDetailVO.setCrPathSeqNo(bdPathDetailVO.getBdPathVO().getCrPathSeqNo());
            String crOpeCode = bdPathDetailVO.getBdPathVO().getCrOpeCode();
            if( crOpeCodeMap.containsKey(crOpeCode))
            {
                bdPathDetailVO.getBdPathVO().setCrOpeCodeDesc(crOpeCodeMap.get(crOpeCode));
            }
            bdPathDetailVO.setToolInfoVOList(new ArrayList<>());
            bdPathDetailVO.setToolInfoVOList(toolInfoVOList.stream().filter(toolInfoVO -> toolInfoVO.getOpeCode().equals(crOpeCode)).collect(Collectors.toList()));
        });
     //  bdPathDetailVOList.sort(Comparator.comparing(BdPathDetailVO::getCrPathSeqNo));
        return bdPathDetailVOList;
    }

    @Override
    public void updateBdPathSeq(BdPathDTO bdPathDTO) {

        BdPath bdPath = this.getById(bdPathDTO.getBdPathId());
        if (ObjectUtil.isNull(bdPath)) {
            log.error("deleteBdPath() The BdPath does not exist or has been deleted");
            throw new XdcWebException(ResponseEnum.ERROR);
        }

        if (ObjectUtil.isEmpty(bdPath.getPvOpeCode())
                && bdPathDTO.getSaveMode().equals(OpeSaveModeEnum.BEFORE.getCode())) {
            throw new XdcWebException(ResponseEnum.ERROR);
        }

        if (ObjectUtil.isEmpty(bdPath.getNxOpeCode())
                && bdPathDTO.getSaveMode().equals(OpeSaveModeEnum.AFTER.getCode())) {
            throw new XdcWebException(ResponseEnum.ERROR);
        }

        transactionTemplate.executeWithoutResult(transactionStatus->{

            // 更新前置工艺关系
            if (ObjectUtil.isNotEmpty(bdPath.getPvOpeCode()) &&  bdPathDTO.getSaveMode().equals(OpeSaveModeEnum.BEFORE.getCode()) ) {

                LambdaQueryWrapper<BdPath> bdPathLambdaQueryWrapper = new LambdaQueryWrapper<>();
                bdPathLambdaQueryWrapper.eq(BdPath::getPathIdFk,bdPath.getPathIdFk())
                        .eq(BdPath::getCrOpeCode,bdPath.getPvOpeCode());
                BdPath bdPathBefore = this.baseMapper.selectOne(bdPathLambdaQueryWrapper);

                // 紧后工艺
                if ( ObjectUtil.isNotEmpty( bdPath.getNxOpeCode() ) ) {
                    LambdaUpdateWrapper<BdPath> updateNxOpeWrapper = new LambdaUpdateWrapper<>();
                    updateNxOpeWrapper.eq(BdPath::getPathIdFk,bdPath.getPathIdFk())
                            .eq(BdPath::getCrOpeCode,bdPath.getNxOpeCode());
                    updateNxOpeWrapper.set(BdPath::getPvOpeCode,bdPath.getPvOpeCode());
                    this.update(updateNxOpeWrapper);
                }

                // 当前工艺和紧前工序
                if (ObjectUtil.isNotNull(bdPathBefore)) {

                    if (ObjectUtil.isNotEmpty(bdPathBefore.getPvOpeCode())){
                        // 紧前紧前工序
                        LambdaUpdateWrapper<BdPath> updatePvOpeWrapper = new LambdaUpdateWrapper<>();
                        updatePvOpeWrapper.eq(BdPath::getPathIdFk,bdPath.getPathIdFk())
                                .eq(BdPath::getCrOpeCode,bdPathBefore.getPvOpeCode());
                        updatePvOpeWrapper.set(BdPath::getNxOpeCode,bdPath.getCrOpeCode());
                        this.update(updatePvOpeWrapper);
                    }


                    // 紧前工序
                    if (ObjectUtil.isNotEmpty(bdPath.getPvOpeCode())) {
                        LambdaUpdateWrapper<BdPath> updateNxOpeWrapper = new LambdaUpdateWrapper<>();
                        updateNxOpeWrapper.eq(BdPath::getPathIdFk,bdPath.getPathIdFk())
                                .eq(BdPath::getCrOpeCode,bdPath.getPvOpeCode());
                        updateNxOpeWrapper.set(BdPath::getPvOpeCode,bdPath.getCrOpeCode());
                        updateNxOpeWrapper.set(BdPath::getNxOpeCode,ObjectUtil.isNull(bdPath.getNxOpeCode())?"":bdPath.getNxOpeCode());
                        // 位号互置换
                        updateNxOpeWrapper.set(BdPath::getCrPathSeqNo,bdPath.getCrPathSeqNo());
                        updateNxOpeWrapper.set(BdPath::getCrOpeSeqNo,Integer.parseInt(bdPath.getCrPathSeqNo().toString()));
                        this.update(updateNxOpeWrapper);
                    }

                    bdPath.setPvOpeCode(bdPathBefore.getPvOpeCode());
                    bdPath.setNxOpeCode(bdPathBefore.getCrOpeCode());

                    // 位号互置换
                    bdPath.setCrPathSeqNo(bdPathBefore.getCrPathSeqNo());
                    bdPath.setCrOpeSeqNo(Integer.parseInt(bdPathBefore.getCrPathSeqNo().toString()));

                }

            }

            // 更新后置工艺关系
            if (ObjectUtil.isNotEmpty(bdPath.getNxOpeCode()) && bdPathDTO.getSaveMode().equals(OpeSaveModeEnum.AFTER.getCode()) ) {

                LambdaQueryWrapper<BdPath> bdPathLambdaQueryWrapper = new LambdaQueryWrapper<>();
                bdPathLambdaQueryWrapper.eq(BdPath::getPathIdFk,bdPath.getPathIdFk())
                        .eq(BdPath::getCrOpeCode,bdPath.getNxOpeCode());
                BdPath bdPathAfter = this.baseMapper.selectOne(bdPathLambdaQueryWrapper);

                // 紧后工序前移
                LambdaUpdateWrapper<BdPath> updateNxOpeWrapper = new LambdaUpdateWrapper<>();
                updateNxOpeWrapper.eq(BdPath::getPathIdFk,bdPath.getPathIdFk())
                        .eq(BdPath::getCrOpeCode,bdPath.getNxOpeCode());
                updateNxOpeWrapper.set(BdPath::getPvOpeCode,ObjectUtil.isEmpty(bdPath.getPvOpeCode())?"":bdPath.getPvOpeCode());
                updateNxOpeWrapper.set(BdPath::getNxOpeCode,bdPath.getCrOpeCode());
                // 位序号仅需调整目标工序后紧后工序，互置
                updateNxOpeWrapper.set(BdPath::getCrPathSeqNo,bdPath.getCrPathSeqNo());
                updateNxOpeWrapper.set(BdPath::getCrOpeSeqNo,Integer.parseInt(bdPath.getCrPathSeqNo().toString()));
                this.update(updateNxOpeWrapper);

                // 紧前工序
                if (ObjectUtil.isNotEmpty(bdPath.getPvOpeCode())) {
                    LambdaUpdateWrapper<BdPath> updatePvOpeWrapper = new LambdaUpdateWrapper<>();
                    updatePvOpeWrapper.eq(BdPath::getPathIdFk,bdPath.getPathIdFk())
                            .eq(BdPath::getCrOpeCode,bdPath.getPvOpeCode());
                    updatePvOpeWrapper.set(BdPath::getNxOpeCode,ObjectUtil.isEmpty(bdPath.getNxOpeCode())?"":bdPath.getNxOpeCode());
                    this.update(updatePvOpeWrapper);
                }


                // 当前工序和紧后工序的紧后工序调整
                if (ObjectUtil.isNotNull(bdPathAfter)) {

                    bdPath.setPvOpeCode(bdPathAfter.getCrOpeCode());
                    bdPath.setNxOpeCode(bdPathAfter.getNxOpeCode());

                    // 调整目标工序位号为紧后工序号，互置
                    bdPath.setCrPathSeqNo(bdPathAfter.getCrPathSeqNo());
                    bdPath.setCrOpeSeqNo(Integer.parseInt(bdPathAfter.getCrPathSeqNo().toString()));

                    // 紧后工序的紧后工序调整
                    if (ObjectUtil.isNotEmpty(bdPathAfter.getNxOpeCode())) {
                        LambdaUpdateWrapper<BdPath> updateNxMoreOpeWrapper = new LambdaUpdateWrapper<>();
                        updateNxMoreOpeWrapper.eq(BdPath::getPathIdFk,bdPath.getPathIdFk())
                                .eq(BdPath::getCrOpeCode,bdPathAfter.getNxOpeCode());
                        updateNxMoreOpeWrapper.set(BdPath::getPvOpeCode,bdPath.getCrOpeCode());
                        this.update(updateNxMoreOpeWrapper);
                    }

                }

            }

            // 更新当前工艺
            this.updateBdPathById(bdPath);

        });


    }


    @Override
    public BdPathVO objectConversion(BdPath s) {
        BdPathVO bdPathVO = super.objectConversion(s);
        bdPathVO.setBdPathiVO(bdPathiService.queryBdPathiById(bdPathVO.getPathIdFk()));
        bdPathVO.setCrBdOpeVO(bdOpeService.queryBdOpeById(bdPathVO.getCrOpeIdFk()));

        return bdPathVO;
    }

    @Override
    public List<BdPathVO> objectConversion(List<BdPath> sList) {
        if (!CollectionUtil.isNotEmpty(sList)) {
            return null;
        } else {
            List<BdPathVO> tList = new ArrayList();
            Iterator var3 = sList.iterator();

            while (var3.hasNext()) {
                BdPath s = (BdPath) var3.next();
                BdPathVO t = this.objectConversion(s);
                Optional.ofNullable(t).ifPresent(tList::add);
            }

            return tList;
        }
    }
    public BdPath getBdPathByPathCodeAndCrOpeCode(String pathCode, String crOpeCode) {
        return bdPathMapper.getBdPathByPathCodeAndCrOpeCode(pathCode,crOpeCode);
    }

    /**
     * 根据工序路线及当前工序获取下一个工序
     */
    @Override
    public String getNxOpeCodeByPathCodeAndCrOpeCode(String pathCode,String opeCode) {
        BdPath bdPath= this.getBdPathByPathCodeAndCrOpeCode(pathCode,opeCode);
        if(bdPath==null || StringUtils.isEmpty(bdPath.getNxOpeCode())){
            throw new XdcWebException(ResponseEnum.ERROR,"工序路线配置有误,找不到下个工序");
        }
        return bdPath.getNxOpeCode();
    }

    @Override
    public List<BdOpeVO> queryOpeCodesForOpeCode(String opeCode) {
        LambdaQueryWrapper<BdPath> bdPathLambdaQueryWrapper = new LambdaQueryWrapper<>();
        bdPathLambdaQueryWrapper.eq(BdPath::getPathCode,"MAIN");
        bdPathLambdaQueryWrapper.orderByAsc(BdPath::getCrPathSeqNo);
        List<BdPath> bdPaths = bdPathMapper.selectList(bdPathLambdaQueryWrapper);

        AtomicBoolean flag = new AtomicBoolean(false);
        List<String> opeCodeList = bdPaths.stream().filter(
                bdPath -> {
                    if (bdPath.getCrOpeCode().equals(opeCode)) {
                        flag.set(true);
                    }
                    return flag.get();
                }
        ).map(BdPath::getCrOpeCode).collect(Collectors.toList());

        if (ObjectUtil.isEmpty(opeCodeList)) {
            return Collections.emptyList();
        }
        return bdOpeService.objectConversion(bdOpeMapper.queryByOpeCodes(opeCodeList));

    }



}
